#include <stdio.h>
#include "memory.h"
#include "tree.h"

extern int lineno;

FUNCTION *makeFUNC(HEAD *head, BODY *body, TAIL *tail) {
	FUNCTION *f;
	f = NEW(FUNCTION);
	f->lineno = lineno;
	f->head = head;
	f->body = body;
	f->tail = tail;
	f->table = NULL;
	return f;
}
HEAD *makeHEAD(char *id, PAR_DECL_LIST *par_decl_list, TYPE *type) {
	HEAD *h;
	h = NEW(HEAD);
	h->lineno = lineno;
	h->id = id;
	h->par_decl_list = par_decl_list;
	h->type = type;
	return h;
}
BODY *makeBODY(DECL_LIST *decl_list, STATEMENT_LIST *statement_list) {
	BODY *b;
	b = NEW(BODY);
	b->lineno = lineno;
	b->decl_list = decl_list;
	b->statement_list = statement_list;
	return b;
}
TAIL *makeTAIL(char *id) {
	TAIL *t;
	t = NEW(TAIL);
	t->lineno = lineno;
	t->id = id;
	return t;
}
TYPE *makeTYPE_id(char *id) {
	TYPE *t;
	t = NEW(TYPE);
	t->lineno = lineno;
	t->kind = type_idK;
	t->val.id = id;
	return t;
}
TYPE *makeTYPE_intconst() {
	TYPE *t;
	t = NEW(TYPE);
	t->lineno = lineno;
	t->kind = intK;
	return t;
}
TYPE *makeTYPE_bool() {
	TYPE *t;
	t = NEW(TYPE);
	t->lineno = lineno;
	t->kind = boolK;
	return t;
}
TYPE *makeTYPE_array(TYPE *type) {
	TYPE *t;
	t = NEW(TYPE);
	t->lineno = lineno;
	t->kind = arrayK;
	t->val.type = type;
	return t;
}
TYPE *makeTYPE_record(VAR_DECL_LIST *var_decl_list) {
	TYPE *t;
	t = NEW(TYPE);
	t->lineno = lineno;
	t->kind = recordK;
	t->val.recordE.var_decl_list = var_decl_list;
	t->val.recordE.table = NULL;
	return t;
}
PAR_DECL_LIST *makePAR_DECL_LIST(VAR_DECL_LIST *var_decl_list) {
	PAR_DECL_LIST *p;
	p = NEW(PAR_DECL_LIST);
	p->lineno = lineno;
	p->var_decl_list = var_decl_list;
	return p;
}
VAR_DECL_LIST *makeVAR_DECL_LIST(VAR_DECL_LIST *var_decl_list,
		VAR_TYPE *var_type) {
	VAR_DECL_LIST *v;
	v = NEW(VAR_DECL_LIST);
	v->lineno = lineno;
	v->kind = var_decl_listK;
	v->var_decl_list = var_decl_list;
	v->var_type = var_type;
	return v;
}
VAR_DECL_LIST *makeVAR_DECL_LIST_BASE(VAR_TYPE *var_type) {
	VAR_DECL_LIST *v;
	v = NEW(VAR_DECL_LIST);
	v->lineno = lineno;
	v->kind = var_decl_list_baseK;
	v->var_decl_list = NULL;
	v->var_type = var_type;
	return v;
}
VAR_TYPE *makeVAR_TYPE(char *id, TYPE *type) {
	VAR_TYPE *v;
	v = NEW(VAR_TYPE);
	v->lineno = lineno;
	v->id = id;
	v->type = type;
	return v;
}
DECL_LIST *makeDECL_LIST(DECL_LIST *decl_list, DECLARATION *declaration) {
	DECL_LIST *d;
	d = NEW(DECL_LIST);
	d->lineno = lineno;
	d->decl_list = decl_list;
	d->declaration = declaration;
	return d;
}
DECLARATION *makeDECL_id(char *id, TYPE *type) {
	DECLARATION *d;
	d = NEW(DECLARATION);
	d->lineno = lineno;
	d->kind = typeidK;
	d->val.DECL_TYPE.id = id;
	d->val.DECL_TYPE.type = type;
	return d;
}
DECLARATION *makeDECL_func(FUNCTION *function) {
	DECLARATION *d;
	d = NEW(DECLARATION);
	d->lineno = lineno;
	d->kind = funcK;
	d->val.function = function;
	return d;
}
DECLARATION *makeDECL_varlist(VAR_DECL_LIST *var_decl_list) {
	DECLARATION *d;
	d = NEW(DECLARATION);
	d->lineno = lineno;
	d->kind = varK;
	d->val.var_decl_list = var_decl_list;
	return d;
}
STATEMENT_LIST *makeSTAT_LIST_BASE(STATEMENT *statement) {
	STATEMENT_LIST *s;
	s = NEW(STATEMENT_LIST);
	s->lineno = lineno;
	s->kind = statement_list_baseK;
	s->statement = statement;
	s->statement_list = NULL;
	return s;
}
STATEMENT_LIST *makeSTAT_LIST(STATEMENT_LIST *statement_list,
		STATEMENT *statement) {
	STATEMENT_LIST *s;
	s = NEW(STATEMENT_LIST);
	s->lineno = lineno;
	s->kind = statement_listK;
	s->statement_list = statement_list;
	s->statement = statement;
	return s;
}
STATEMENT *makeSTAT_RETURN(EXPRESSION *return_expression) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = returnK;
	s->val.return_expression = return_expression;
	return s;
}
STATEMENT *makeSTAT_WRITE(EXPRESSION *write_expression) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = writeK;
	s->val.write_expression = write_expression;
	return s;
}
STATEMENT *makeSTAT_ALLOCATE(VARIABLE *variable, OPT_LENGTH *opt_length) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = allocateK;
	s->val.allocateE.variable = variable;
	s->val.allocateE.opt_length = opt_length;
	return s;
}
STATEMENT *makeSTAT_VAR(VARIABLE *variable, EXPRESSION *expression) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = variableK;
	s->val.variableE.variable = variable;
	s->val.variableE.expression = expression;
	return s;
}
STATEMENT *makeSTAT_IF(EXPRESSION *expression, STATEMENT *statement,
		OPT_ELSE *opt_else) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = ifK;
	s->val.ifE.expression = expression;
	s->val.ifE.statement = statement;
	s->val.ifE.opt_else = opt_else;
	return s;
}
STATEMENT *makeSTAT_WHILE(EXPRESSION *expression, STATEMENT *statement) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = whileK;
	s->val.whileE.expression = expression;
	s->val.whileE.statement = statement;
	return s;
}
STATEMENT *makeSTAT_STAT_LIST(STATEMENT_LIST *statement_list) {
	STATEMENT *s;
	s = NEW(STATEMENT);
	s->lineno = lineno;
	s->kind = statementlistK;
	s->val.statement_list = statement_list;
	return s;
}
OPT_LENGTH *makeLENGTH(EXPRESSION *expression) {
	OPT_LENGTH *o;
	o = NEW(OPT_LENGTH);
	o->lineno = lineno;
	o->expression = expression;
	return o;
}
OPT_ELSE *makeELSE(STATEMENT *statement) {
	OPT_ELSE *o;
	o = NEW(OPT_ELSE);
	o->lineno = lineno;
	o->statement = statement;
	return o;
}
VARIABLE *makeVAR_id(char *id) {
	VARIABLE *v;
	v = NEW(VARIABLE);
	v->lineno = lineno;
	v->kind = var_idK;
	v->val.id = id;
	v->type = 0;
	return v;
}
VARIABLE *makeVAR_exp(VARIABLE *variable, EXPRESSION *expression) {
	VARIABLE *v;
	v = NEW(VARIABLE);
	v->lineno = lineno;
	v->kind = var_expK;
	v->val.var_expE.variable = variable;
	v->val.var_expE.expression = expression;
	v->type = 0;
	return v;
}
VARIABLE *makeVAR_dot(VARIABLE *variable, char *id) {
	VARIABLE *v;
	v = NEW(VARIABLE);
	v->lineno = lineno;
	v->kind = var_dotK;
	v->val.var_dotE.variable = variable;
	v->val.var_dotE.id = id;
	v->type = 0;
	return v;
}
EXPRESSION *makeEXP_eq(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = eqK;
	e->val.EXP_eq.left = left;
	e->val.EXP_eq.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_neq(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = neqK;
	e->val.EXPneq.left = left;
	e->val.EXPneq.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_leq(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = leqK;
	e->val.EXP_leq.left = left;
	e->val.EXP_leq.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_geq(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = geqK;
	e->val.EXP_geq.left = left;
	e->val.EXP_geq.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_and(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = andK;
	e->val.EXP_and.left = left;
	e->val.EXP_and.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_or(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = orK;
	e->val.EXP_or.left = left;
	e->val.EXP_or.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_plus(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = plusK;
	e->val.EXP_plus.left = left;
	e->val.EXP_plus.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_minus(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = minusK;
	e->val.EXP_minus.left = left;
	e->val.EXP_minus.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_lessthan(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = leK;
	e->val.EXP_lessthan.left = left;
	e->val.EXP_lessthan.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_greaterthan(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = grK;
	e->val.EXP_greaterthan.left = left;
	e->val.EXP_greaterthan.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_times(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = timesK;
	e->val.EXP_times.left = left;
	e->val.EXP_times.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_div(EXPRESSION *left, EXPRESSION *right) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = divK;
	e->val.EXP_div.left = left;
	e->val.EXP_div.right = right;
	e->type = 0;
	return e;
}
EXPRESSION *makeEXP_term(TERM *term) {
	EXPRESSION *e;
	e = NEW(EXPRESSION);
	e->lineno = lineno;
	e->kind = termK;
	e->val.term = term;
	e->type = 0;
	return e;
}
TERM *makeTERM_var(VARIABLE *variable) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_varK;
	t->val.variable = variable;
	t->type = 0;
	return t;
}
TERM *makeTERM_id(char *id, ACT_LIST *act_list) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_idK;
	t->val.term_idE.id = id;
	t->val.term_idE.act_list = act_list;
	t->type = 0;
	return t;
}
TERM *makeTERM_exp(EXPRESSION *expression) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_expK;
	t->val.expression = expression;
	t->type = 0;
	return t;
}
TERM *makeTERM_not(TERM *term) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_notK;
	t->val.term = term;
	t->type = 0;
	return t;
}
TERM *makeTERM_act_exp(EXPRESSION *expression) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_act_expK;
	t->val.act_expression = expression;
	t->type = 0;
	return t;
}
TERM *makeTERM_num(int num) {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_numK;
	t->val.number = num;
	t->type = 0;
	return t;
}
TERM *makeTERM_true() {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_trueK;
	t->val.bn = "true";
	t->type = 0;
	return t;
}
TERM *makeTERM_false() {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_falseK;
	t->val.bn = "false";
	t->type = 0;
	return t;
}
TERM *makeTERM_null() {
	TERM *t;
	t = NEW(TERM);
	t->lineno = lineno;
	t->kind = term_nullK;
	t->val.bn = "null";
	t->type = 0;
	return t;
}
ACT_LIST *makeACT_LIST(EXP_LIST *exp_list) {
	ACT_LIST *a;
	a = NEW(ACT_LIST);
	a->lineno = lineno;
	a->exp_list = exp_list;
	return a;
}
EXP_LIST *makeEXP_LIST_BASE(EXPRESSION *expression) {
	EXP_LIST *e;
	e = NEW(EXP_LIST);
	e->lineno = lineno;
	e->kind = exp_list_baseK;
	e->expression = expression;
	e->exp_list = NULL;
	return e;
}
EXP_LIST *makeEXP_LIST(EXP_LIST *exp_list, EXPRESSION *expression) {
	EXP_LIST *e;
	e = NEW(EXP_LIST);
	e->lineno = lineno;
	e->kind = exp_listK;
	e->exp_list = exp_list;
	e->expression = expression;
	return e;
}
